package com.aegis.core.manager;

import com.aegis.core.constants.AegisTokenRedisConstants;
import com.aegis.core.model.AegisAppGroup;
import com.aegis.core.model.AegisAppGroupPermission;
import com.aegis.core.model.AegisUserApi;
import com.aegis.core.model.AegisUserPermission;
import com.aegis.core.utils.AegisCommonUtil;

import java.util.*;

/**
 * @Author wuweixin
 *
 * @Version 1.0
 * @Descritube 用户权限管理
 */
public class AegisUserPermissionManager {

    private static final String SET_GROUP_LUA_SCRIPT =
            "local key = KEYS[1] " +
                    "if tonumber(ARGV[1]) == 1 then " +
                    "    redis.call('DEL', key) " +
                    "end " +
                    "for i = 2, #ARGV, 2 do " +
                    "    redis.call('HSET', key, ARGV[i], ARGV[i + 1]) " +
                    "end " +
                    "return 1";

    private AegisUserPermissionManager() {
        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
    }

//    /**
//     * 设置应用分组的权限，即RBAC模型中，角色(group)可以访问哪些api
//     *
//     * @param appId
//     * @param groupPermissions
//     */
//    public static void setGroupPermission(String appId, List<AegisAppGroupPermission> groupPermissions) {
//        setGroupPermission(appId, groupPermissions, true);
//    }

//    /**
//     * 设置应用分组的权限，即RBAC模型中，角色(group)可以访问哪些api
//     *
//     * @param appId
//     * @param groupPermissions
//     */
//    public static void setGroupPermission(String appId, List<AegisAppGroupPermission> groupPermissions, boolean clear) {
//        AegisAppManager.checkAppExisting(appId);
//        if (clear) {
//            clearGroupPermission(appId);
//        }
//        for (AegisAppGroupPermission groupPermission : groupPermissions) {
//            AegisComponentManager.getAegisDao().hset(AegisTokenRedisConstants
//                    .getAppGroup(appId), String.valueOf(groupPermission.getGroupKey()), groupPermission.getApis(), -1);
//        }
//
//    }

    /**
     * 添加应用分组的权限，即RBAC模型中，角色(group)可以访问哪些api
     *
     * @param appId
     * @param groupPermissions
     */
    public static void addGroupPermission(String appId, List<AegisAppGroupPermission> groupPermissions) {
        if (AegisCommonUtil.isCollectionEmpty(groupPermissions)) {
            return;
        }
        for (AegisAppGroupPermission groupPermission : groupPermissions) {
            AegisComponentManager.getAegisDao().hset(AegisTokenRedisConstants
                    .getAppGroup(appId), groupPermission.getGroupKey(), groupPermission, -1);
        }
    }

    /**
     * 删除权限组
     *
     * @param appId
     * @param groupKey
     */
    public static void removeGroupPermission(String appId, String groupKey) {
        AegisComponentManager.getAegisDao().hdel(AegisTokenRedisConstants.getAppGroup(appId), groupKey);
    }

    /**
     * 清空应用权限组
     *
     * @param appId
     */
    public static void clearGroupPermission(String appId) {
        AegisComponentManager.getAegisDao().del(AegisTokenRedisConstants.getAppGroup(appId));
    }

    /**
     * 获得应用分组
     *
     * @param appId
     * @return
     */
    public static List<AegisAppGroupPermission> getAppGroup(String appId, String... groupKeys) {
        AegisAppGroup aegisAppGroup = new AegisAppGroup();
        aegisAppGroup.setAppId(appId);
        List<AegisAppGroupPermission> groupPermissions = new ArrayList<>();
        for (String s : groupKeys) {
            Object hget = AegisComponentManager.getAegisDao().hget(AegisTokenRedisConstants.getAppGroup(appId), s);
            if (hget == null) {
                continue;
            }
            AegisAppGroupPermission value = (AegisAppGroupPermission) hget;
            groupPermissions.add(value);
        }
        aegisAppGroup.setGroupPermissions(groupPermissions);
        return aegisAppGroup.getGroupPermissions();
    }


    /**
     * 获得应用分组
     *
     * @param appId
     * @return
     */
    public static List<AegisAppGroupPermission> getAppGroup(String appId) {
        Map<Object, Object> hmget = AegisComponentManager.getAegisDao().hmget(AegisTokenRedisConstants.getAppGroup(appId));
        AegisAppGroup aegisAppGroup = new AegisAppGroup();
        aegisAppGroup.setAppId(appId);
        if (hmget != null && !hmget.isEmpty()) {
            List<AegisAppGroupPermission> groupPermissions = new ArrayList<>();
            for (Map.Entry<Object, Object> entry : hmget.entrySet()) {
                AegisAppGroupPermission value = (AegisAppGroupPermission) entry.getValue();
                groupPermissions.add(value);
            }
            aegisAppGroup.setGroupPermissions(groupPermissions);
        }
        return aegisAppGroup.getGroupPermissions();
    }

    /**
     * 获得应用分组
     *
     * @param appId
     * @return
     */
    public static List<AegisAppGroupPermission> getNotNullAppGroup(String appId) {
        return Optional.ofNullable(getAppGroup(appId)).orElse(new ArrayList<>());
    }


    /**
     * 添加用户的组别
     *
     * @param userId
     * @param groupKeys
     */
    public static void addUserGroup(String appId, Object userId, List<String> groupKeys) {
        AegisUserPermission userPermission = getNotNullUserPermission(appId, userId);
        List<String> existingGroup = Optional.ofNullable(userPermission.getGroup()).orElse(new ArrayList<>());
        if (existingGroup.addAll(groupKeys)) {
            userPermission.setGroup(new ArrayList<>(new HashSet<>(existingGroup)));
            setUserPermission(userPermission);
        }
    }

    /**
     * 设置用户的组别
     *
     * @param userId
     * @param groupKeys
     */
    public static void setUserGroup(String appId, Object userId, List<String> groupKeys) {
        AegisUserPermission userPermission = getNotNullUserPermission(appId, userId);
        userPermission.setGroup(groupKeys);
        setUserPermission(userPermission);
    }

    /**
     * 清空用户的组别
     *
     * @param userId
     */
    public static void clearUserGroup(String appId, Object userId) {
        AegisUserPermission userPermission = getUserPermission(appId, userId);
        if (userPermission == null) {
            return;
        }
        userPermission.setGroup(null);
        setUserPermission(userPermission);
    }

    /**
     * 新添加的权限接口
     *
     * @param allowApi
     */
    public static void addUserAllowApiPermission(String appId, Object userId, List<AegisUserApi> allowApi) {
        addApiPermission(appId, userId, allowApi, true);
    }

    /**
     * 新添加的权限接口
     *
     * @param rejectApi
     */
    public static void addUserRejectApiPermission(String appId, Object userId, List<AegisUserApi> rejectApi) {
        addApiPermission(appId, userId, rejectApi, false);
    }


    /**
     * 刷新api访问权限，会替换原有的权限
     *
     * @param allowApi
     */
    public static void setUserAllowApiPermission(String appId, Object userId, List<AegisUserApi> allowApi) {
        setUserApiPermission(appId, userId, allowApi, true);
    }

    /**
     * 刷新api访问权限，会替换原有的权限
     *
     * @param reject
     */
    public static void setUserRejectApiPermission(String appId, Object userId, List<AegisUserApi> reject) {
        setUserApiPermission(appId, userId, reject, false);

    }


    /**
     * 清空用户允许访问的API接口
     *
     * @param userId
     */
    public static void clearUserAllowApi(String appId, Object userId) {
        clearApiPermission(appId, userId, true);
    }

    /**
     * 清空用户被禁止访问的API接口
     *
     * @param userId
     */
    public static void clearUserRejectApi(String appId, Object userId) {
        clearApiPermission(appId, userId, false);
    }


    /**
     * 获取用户权限信息
     *
     * @param userId
     * @return
     */
    public static AegisUserPermission getUserPermission(String appId, Object userId) {
        return (AegisUserPermission) AegisComponentManager.getAegisDao().getObject(AegisTokenRedisConstants.getUserPermission(appId, userId));
    }


    /**
     * 设置用户权限信息
     *
     * @param aegisUserPermission
     */
    public static void setUserPermission(AegisUserPermission aegisUserPermission) {
        if (aegisUserPermission == null) {
            throw new IllegalArgumentException("aegisUserPermission is empty");
        }
        if (AegisCommonUtil.isStringBlank(aegisUserPermission.getUserId() + "")) {
            throw new IllegalArgumentException("userId is empty");
        }
        if (AegisCommonUtil.isStringBlank(aegisUserPermission.getAppId())) {
            throw new IllegalArgumentException("appId is empty");
        }
        AegisComponentManager.getAegisDao().setObject(AegisTokenRedisConstants.getUserPermission(aegisUserPermission.getAppId(), aegisUserPermission.getUserId()), aegisUserPermission, -1);

    }

    /**
     * @param userId
     * @return
     */
    private static AegisUserPermission getNotNullUserPermission(String appId, Object userId) {
        AegisUserPermission aegisUserPermission = Optional.ofNullable(getUserPermission(appId, userId)).orElse(new AegisUserPermission());
        aegisUserPermission.setAppId(appId);
        aegisUserPermission.setUserId(userId);
        return aegisUserPermission;
    }

    private static void clearApiPermission(String appId, Object userId, boolean isAllow) {
        AegisUserPermission userPermission = getUserPermission(appId, userId);
        if (userPermission == null) {
            return;
        }
        if (isAllow) {
            userPermission.setAllowApi(null);
        } else {
            userPermission.setRejectApi(null);
        }
        setUserPermission(userPermission);
    }


    private static void addApiPermission(String appId, Object userId, List<AegisUserApi> api, boolean isAllow) {
        if (api == null || api.isEmpty()) {
            throw new IllegalArgumentException("api is null or empty");
        }

        AegisUserPermission userPermission = getNotNullUserPermission(appId, userId);

        // 选择对应的 API 列表
        List<AegisUserApi> existingApi = isAllow ? userPermission.getAllowApi() : userPermission.getRejectApi();
        if (existingApi == null) {
            existingApi = new ArrayList<>();
        }

        if (existingApi.addAll(api)) {
            List<AegisUserApi> uniqueApi = new ArrayList<>(new HashSet<>(existingApi));
            if (isAllow) {
                userPermission.setAllowApi(uniqueApi);
            } else {
                userPermission.setRejectApi(uniqueApi);
            }
            setUserPermission(userPermission);
        }
    }

    private static void setUserApiPermission(String appId, Object userId, List<AegisUserApi> apis, boolean isAllow) {
        AegisUserPermission userPermission = getNotNullUserPermission(appId, userId);
        if (isAllow) {
            userPermission.setAllowApi(apis);
        } else {
            userPermission.setRejectApi(apis);
        }
        setUserPermission(userPermission);
    }


}
